//@author A0100976E
package tasky.tests;
import static org.junit.Assert.*;

import java.text.ParseException;
import java.util.ArrayList;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormatterBuilder;
import org.joda.time.format.DateTimeParser;
import org.junit.Test;

import tasky.commons.Task;
import tasky.logic.AddParser;

public class AddParserTest {


	AddParser addParse = new AddParser();
	Task deadlineTask, floatTask, labelAndPriorityTask, labelTask,
			priorityFalseTask, priorityOnlyTask, labelOnlyTask;
	DateTime deadline, start, end;
	
	private static final String ERROR_INVALID_DATE = "Date entered is invalid.\n";
	private static final String ERROR_END_DATE_BEFORE_START_DATE = "End date cannot be before start date\n";
	private static final String ERROR_NO_LABEL_SET = "No label is entered\n";
	private static final String EMPTY_LABEL = "";
	
	private static final String DD_MMMM_YYYY_HH_MM = "dd/MMMM/yyyy-HH:mm";
	private static final String DD_MM_YYYY_HH_MM = "dd/MM/yyyy-HH:mm";
	private static final String DD_MMMM_YY_HH_MM = "dd/MMMM/yy-HH:mm";
	private static final String DD_MM_YY_HH_MM = "dd/MM/yy-HH:mm";
	private static final String DD_MMMM_YYYY = "dd/MMMM/yyyy";
	private static final String DD_MM_YYYY = "dd/MM/yyyy";
	private static final String DD_MMMM_YY = "dd/MMMM/yy";
	private static final String DD_MM_YY = "dd/MM/yy";
	
	
	@Test
	public void testParse() throws ParseException {
		Task testTask = new Task();
		ArrayList<Task> taskslist = new ArrayList<Task>();
		AddParser addParser = new AddParser();
		DateTimeParser[] parsers = {

		DateTimeFormat.forPattern(DD_MM_YY).getParser(),
				DateTimeFormat.forPattern(DD_MMMM_YY).getParser(),
				DateTimeFormat.forPattern(DD_MM_YYYY).getParser(),
				DateTimeFormat.forPattern(DD_MMMM_YYYY).getParser(),
				DateTimeFormat.forPattern(DD_MM_YY_HH_MM).getParser(),
				DateTimeFormat.forPattern(DD_MMMM_YY_HH_MM).getParser(),
				DateTimeFormat.forPattern(DD_MM_YYYY_HH_MM).getParser(),
				DateTimeFormat.forPattern(DD_MMMM_YYYY_HH_MM).getParser(), };

		DateTimeFormatter formatter = new DateTimeFormatterBuilder().append(
				null, parsers).toFormatter();
		DateTime date;

		String input0 = EMPTY_LABEL;
		testTask.setContent(input0);
		String output0 = validate(testTask);
		assertEquals(output0, validate(addParser.parse(input0, taskslist)));

		String input1 = "do homework";
		testTask.setContent(input1);
		String output1 = validate(testTask);
		assertEquals(output1, validate(addParser.parse(input1, taskslist)));
		
		String input2 = "do homework -by 1/1/1111";
		date = formatter.parseDateTime("1/1/1111");
		testTask.setDeadline(date);
		String output2 = validate(testTask);
		assertEquals(output2, validate(addParser.parse(input2, taskslist)));

		String input3 = "do homework -by 1/1/11";
		date = formatter.parseDateTime("1/1/11");
		testTask.setDeadline(date);
		String output3 = validate(testTask);
		assertEquals(output3, validate(addParser.parse(input3, taskslist)));

		String input4 = "do homework -by 1/jan/11";
		date = formatter.parseDateTime("1/jan/11");
		testTask.setDeadline(date);
		String output4 = validate(testTask);
		assertEquals(output4, validate(addParser.parse(input4, taskslist)));
		
		String input5 = "do homework -by 31/jan/11";
		date = formatter.parseDateTime("31/jan/11");
		testTask.setDeadline(date);
		String output5 = validate(testTask);
		assertEquals(output5, validate(addParser.parse(input5, taskslist)));
		
		String input6 = "do homework -by 31/jul/11";
		date = formatter.parseDateTime("31/jul/11");
		testTask.setDeadline(date);
		String output6 = validate(testTask);
		assertEquals(output6, validate(addParser.parse(input6, taskslist)));
		
		// boundary test case when the day given is beyond 31
		String input7 = "do homework -by 32/jan/11";
		try{
			addParser.parse(input7, taskslist);
		}catch (ParseException e){
			assertEquals(ERROR_INVALID_DATE,e.getMessage());
		}
		
		// Equivalent partition test case when the day given is negative
		String input8 = "do homework -by -1/jan/11";
		try{
			addParser.parse(input8, taskslist);
		}catch (ParseException e){
			assertEquals(ERROR_INVALID_DATE,e.getMessage());
		}
		
		// boundary test case for leap year
		String input9 = "do homework -by 29/2/14";
		try{
			addParser.parse(input9, taskslist);
		}catch (ParseException e){
			assertEquals(ERROR_INVALID_DATE,e.getMessage());
		}
		
		// Equivalent partition test case when the day give is negative
		String input10 = "do homework -from -1/jan/11 -to 2/jan/11";
		try{
			addParser.parse(input10, taskslist);
		}catch (ParseException e){
			assertEquals(ERROR_INVALID_DATE,e.getMessage());
		}
		String input11 = "do homework -from 1/jan/11 -to 2/jan/11";
		testTask = new Task();
		testTask.setContent("do homework");
		date = formatter.parseDateTime("1/jan/11");
		testTask.setStart(date);
		date = formatter.parseDateTime("2/jan/11");
		testTask.setEnd(date);
		String output11 = validate(testTask);
		assertEquals(output11,validate(addParser.parse(input11,taskslist)));
		
		String input12 = "do homework -from 1/jan/11-15:30 -to 2/jan/11-16:30";
		testTask = new Task();
		testTask.setContent("do homework");
		date = formatter.parseDateTime("1/jan/11-15:30");
		testTask.setStart(date);
		date = formatter.parseDateTime("2/jan/11-16:30");
		testTask.setEnd(date);
		String output12 = validate(testTask);
		assertEquals(output12,validate(addParser.parse(input12,taskslist)));
		
		String input13 = "do homework -from 1/1/11-15:30 -to 2/mar/11-16:30";
		testTask = new Task();
		testTask.setContent("do homework");
		date = formatter.parseDateTime("1/1/11-15:30");
		testTask.setStart(date);
		date = formatter.parseDateTime("2/mar/11-16:30");
		testTask.setEnd(date);
		String output13 = validate(testTask);
		assertEquals(output13,validate(addParser.parse(input13,taskslist)));
		
		// Equivalent partition test case when the year given is negative
		String input14 = "do homework -from 1/1/11-15:30 -to 2/mar/11-25:30";
		String output14 = ERROR_INVALID_DATE;
		String actualOutput14 = null;
		try{
			addParser.parse(input14,taskslist);
		}catch(ParseException e){
			actualOutput14 = e.getMessage();
		}
		assertEquals(output14,actualOutput14);
		
		String input15 = "do homework -!";
		testTask = new Task();
		testTask.setContent("do homework");
		testTask.setPriority(true);
		String output15 = validate(testTask);
		assertEquals(output15,validate(addParser.parse(input15,taskslist)));
		
		String input16 = "do homework -from 1/jan/11-15:30 -to 2/jan/11-16:30 -!";
		testTask = new Task();
		testTask.setContent("do homework");
		date = formatter.parseDateTime("1/jan/11-15:30");
		testTask.setStart(date);
		date = formatter.parseDateTime("2/jan/11-16:30");
		testTask.setEnd(date);
		testTask.setPriority(true);
		String output16 = validate(testTask);
		assertEquals(output16,validate(addParser.parse(input16,taskslist)));
		
		String input17 = "do homework -by 31/jan/11 -!";
		date = formatter.parseDateTime("31/jan/11");
		testTask.setDeadline(date);
		testTask.setPriority(true);
		String output17 = validate(testTask);
		assertEquals(output17, validate(addParser.parse(input17, taskslist)));
		
		String input18 = "do homework -from 1/jan/11-15:30 -to 2/jan/11-16:30 -! -label homework";
		testTask = new Task();
		testTask.setContent("do homework");
		date = formatter.parseDateTime("1/jan/11-15:30");
		testTask.setStart(date);
		date = formatter.parseDateTime("2/jan/11-16:30");
		testTask.setEnd(date);
		testTask.setLabel("homework");
		testTask.setPriority(true);
		String output18 = validate(testTask);
		assertEquals(output18,validate(addParser.parse(input18,taskslist)));
		
		String input19 = "do homework -by 31/jan/11 -label homework -!";
		date = formatter.parseDateTime("31/jan/11");
		testTask.setDeadline(date);
		testTask.setPriority(true);
		testTask.setLabel("homework");
		String output19 = validate(testTask);
		assertEquals(output19, validate(addParser.parse(input19, taskslist)));
		
		// Equivalent partition test case when no label is given
		String input20 = "-label";
		String actualOutput20 = null;
		try{
			validate(addParser.parse(input20, taskslist));
		} catch (ParseException e){
			actualOutput20 = e.getMessage();
		}
		assertEquals(ERROR_NO_LABEL_SET,actualOutput20);
		
		String input21 = "do homework -by 31/jan/11 -label -!";
		String actualOutput21 = null;
		try{
			validate(addParser.parse(input21, taskslist));
		} catch (ParseException e){
			actualOutput21 = e.getMessage();
		}
		assertEquals(ERROR_NO_LABEL_SET,actualOutput21);
		
		// Equivalent partition test case when no label is given
		String input22 = "do homework -by 31/jan/11 -! -label ";
		String actualOutput22 = null;
		try{
			validate(addParser.parse(input22, taskslist));
		} catch (ParseException e){
			actualOutput22 = e.getMessage();
		}
		assertEquals(ERROR_NO_LABEL_SET,actualOutput22);
		
		// Equivalent partition test case when end date is before start date 
		String input23 = "do homework -from 31/jan/11 -to 30/jan/11";
		String actualOutput23 = null;
		try{
			validate(addParser.parse(input23, taskslist));
		} catch (ParseException e){
			actualOutput23 = e.getMessage();
		}
		assertEquals(ERROR_END_DATE_BEFORE_START_DATE,actualOutput23);
		
		

	}

	public String validate(Task task) {

		DateTime date;
		StringBuilder validator = new StringBuilder();
		validator.append(task.getContent());
		if (task.getDeadline() != null) {
			date = task.getDeadline();
			validator.append(date.getHourOfDay());
			validator.append(date.getMinuteOfHour());
		} else if (task.getStart() != null) {
			date = task.getStart();
			validator.append(date.getHourOfDay());
			validator.append(date.getMinuteOfHour());
			date = task.getEnd();
			validator.append(date.getHourOfDay());
			validator.append(date.getMinuteOfHour());
		}
		validator.append(task.getLabel());
		validator.append(task.isDone());
		validator.append(task.isPriority());
		return validator.toString();

	}

	public void printToConsole(Task task1, Task task2) {
		System.out.println("task1: " + validate(task1));
		System.out.println("task2: " + validate(task2));
	}

}
